﻿// CAnimationPlayer.cs
// Author: Gant Briseno
#region Using Statements
using Microsoft.Xna.Framework;
using Casters.source.Objects;
using Microsoft.Xna.Framework.Graphics;
using Casters.source.Managers;
using Microsoft.Xna.Framework.Storage;
using System.IO;
#endregion

namespace Casters.source.Animation
{
    /// <summary>
    /// Loads frames
    /// Looping animations
    /// Rendering animation
    /// </summary>
    public class CAnimationPlayer
    {
        // Private
        private Texture2D m_AttackTexture;
        private Texture2D m_CollisionTexture;
        private Texture2D m_SpriteSheet;
        private CBaseObject m_Owner;
        private float m_ElapsedTime;

        // Public
        public CAnimation m_Animation;
        public int m_CurrentFrame;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="owner">Owner of this animation player</param>
        public CAnimationPlayer(CBaseObject owner)
        {
            CGame game = CGame.GetInstance();
            m_Owner = owner;
        }

        /// <summary>
        /// Returns the origin of the current frame
        /// </summary>
        public Vector2 Origin()
        {
            return new Vector2(m_Animation.m_FrameList[m_CurrentFrame].m_ImageRect.Width / 2,
                m_Animation.m_FrameList[m_CurrentFrame].m_ImageRect.Height / 2);
        }

        /// <summary>
        /// Sets the animation you'd like to be currently played
        /// </summary>
        /// <param name="animation"></param>
        public void SetAnimation(CAnimation animation)
        {
            if (m_Animation == animation)
                return;

            m_Animation = animation;
            m_Animation.m_bIsDonePlaying = m_Animation.m_bHasAttacked = false;
            m_CurrentFrame = 0;
            m_ElapsedTime = 0f;
        }

        /// <summary>
        /// Updates the current frame based on it's time on screen
        /// </summary>
        /// <param name="_dt">Delta Time</param>
        public void Update(float _dt)
        {
            m_ElapsedTime += _dt;

            if (m_ElapsedTime > m_Animation.m_FrameList[m_CurrentFrame].m_FrameTime)
            {
                m_ElapsedTime = 0f;
                ++m_CurrentFrame;

                if (m_Animation.m_bIsLooping && m_CurrentFrame == m_Animation.m_FrameCount)
                {
                    m_CurrentFrame = 0;
                }
                else if (m_CurrentFrame == m_Animation.m_FrameCount)
                {
                    m_Animation.m_bIsDonePlaying = true;
                    m_CurrentFrame = m_Animation.m_FrameCount - 1;
                }
                else
                    m_Animation.m_bIsDonePlaying = false;
            }
        }

        public void Draw()
        {
            if (m_Animation == null)
                return;

            Vector2 camPos = CGame.GetInstance().m_Camera.m_vPosition;

            // Debug for drawing the Collision and Attack rects
            if (CGame.GetInstance().bDebug)
            {
                Rectangle collide = new Rectangle((int)(m_Animation.m_FrameList[m_CurrentFrame].m_CollideRect.Left + camPos.X),
                    (int)(m_Animation.m_FrameList[m_CurrentFrame].m_CollideRect.Top + camPos.Y),
                    m_Animation.m_FrameList[m_CurrentFrame].m_CollideRect.Width,
                    m_Animation.m_FrameList[m_CurrentFrame].m_CollideRect.Height);

                Rectangle attack = new Rectangle((int)(m_Animation.m_FrameList[m_CurrentFrame].m_AttackRect.Left + camPos.X),
                    (int)(m_Animation.m_FrameList[m_CurrentFrame].m_AttackRect.Top + camPos.Y),
                    m_Animation.m_FrameList[m_CurrentFrame].m_AttackRect.Width,
                    m_Animation.m_FrameList[m_CurrentFrame].m_AttackRect.Height);

                CRenderEngine.Draw(m_CollisionTexture, collide, Color.White);
                CRenderEngine.Draw(m_AttackTexture, attack, Color.White);
            }

            Vector2 pos = m_Owner.m_vPosition - m_Animation.m_FrameList[m_CurrentFrame].m_AnchorPoint;

            float zoom = CGame.GetInstance().m_Camera.m_fZoom;
            CRenderEngine.Draw(m_SpriteSheet, pos * zoom,
                m_Animation.m_FrameList[m_CurrentFrame].m_ImageRect, Color.White, 0f, Origin(), zoom, SpriteEffects.None, 0f);
        }

        public CAnimation[] LoadAnimation(string filename)
        {
            CAnimation[] loadedAnimations;
            CFrame[] frameList;
            string name;
            int frameCount;
            bool isLooping;
            string filepath = "Content/Animations/" + filename + ".bin";

            // Frame variables
            Vector2 anchor = Vector2.Zero;
            Vector2 emitter = Vector2.Zero;
            Rectangle render = Rectangle.Empty;
            Rectangle collision = Rectangle.Empty;
            Rectangle attack = Rectangle.Empty;
            int nothing = 0;
            int frameTime = 0;
            string trigger = string.Empty;

            using (BinaryReader br = new BinaryReader(TitleContainer.OpenStream(filepath)))
            {
                // not used, but required we move the pointer
                int version = br.ReadInt32();

                // Image used for the animations
                string imageFilename = br.ReadString();

                // Load the texture
                string[] temp = imageFilename.Split('.');                
                m_SpriteSheet = CGame.GetInstance().Content.Load<Texture2D>("Animations/Textures/" + temp[0]); // TODO: add in filepath for sprite sheets

                // Get number of animations and create the list
                int numAnimations = br.ReadInt32();
                loadedAnimations = new CAnimation[numAnimations];

                // Loop through each animation
                for (int i = 0; i < numAnimations; ++i)
                {
                    name = br.ReadString();
                    frameCount = br.ReadInt32();
                    frameList = new CFrame[frameCount];
                    isLooping = br.ReadBoolean();

                    // TODO: loop through frames
                    for (int j = 0; j < frameCount; ++j)
                    {
                        // Anchor point
                        anchor.X = (float)br.ReadInt32();
                        anchor.Y = (float)br.ReadInt32();

                        // Emitter position for particles
                        emitter.X = (float)br.ReadInt32();
                        emitter.Y = (float)br.ReadInt32();

                        // Image rect
                        render.X = br.ReadInt32();
                        render.Y = br.ReadInt32();
                        render.Width = br.ReadInt32();
                        render.Height = br.ReadInt32();
                        
                        // Collision rect
                        collision.X = br.ReadInt32();
                        collision.Y = br.ReadInt32();
                        collision.Width = br.ReadInt32();
                        collision.Height = br.ReadInt32();

                        // Attack rect
                        attack.X = br.ReadInt32();
                        attack.Y = br.ReadInt32();
                        attack.Width = br.ReadInt32();
                        attack.Height = br.ReadInt32();

                        // rest of the frame data
                        nothing = br.ReadInt32();
                        frameTime = br.ReadInt32();
                        trigger = br.ReadString();

                        frameList[j] = new CFrame(anchor, attack, collision, render, 
                            (float)(frameTime * 0.001f), trigger);
                    }

                    // QUICK FIX!
                    // THIS IS NOT WORKING IN THE EDITOR
                    // WILL HAVE TO MANUALLY SET THIS TO TRUE FOR LOOPING ANIMATIONS
                    isLooping = true;

                    loadedAnimations[i] = new CAnimation(name, frameCount, isLooping, frameList);
                }
            }

            return loadedAnimations;
        }
    }
}
